﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace LoLEdit
{
    [DefaultEvent("")]
    public partial class ctlSegmentPanel : UserControl
    {
        #region Private Members

        public enum SegmentTypeEnum
        {
            Integers,
            Floats,
            Booleans,
            Strings,
            RGB_Integers,
            RGB_Floats,
            XY_Integers,
            XY_Floats,
            RGBA_Integers,
            RGBA_Floats
        } //end SegmentType

        private SegmentTypeEnum m_SegType;
        private Boolean m_HideKeys;
        private Boolean m_UnlockKeyNames;

        private Dictionary<UInt32, RowControls> m_Rows;

        #endregion Private Members

        /// <summary>
        /// Constructor
        /// </summary>
        public ctlSegmentPanel()
        {
            m_SegType = SegmentTypeEnum.RGBA_Integers;
            m_HideKeys = false;
            m_UnlockKeyNames = false;

            m_Rows = new Dictionary<UInt32, RowControls>();

            InitializeComponent();
        } //end ctlSegmentPanel

        /// <summary>
        /// Destructor ... not really necessary in C#... but sure why not.
        /// </summary>
        ~ctlSegmentPanel()
        {
            //Cleanup all row controls
            foreach (RowControls row in m_Rows.Values)
            {
                row.Dispose();
            } //end foreach

            m_Rows.Clear();
        } //end ~ctlSegmentPanel()

        #region Public Properties

        /// <summary>
        /// Gets/Sets the Label for this segment control
        /// </summary>
        [Description("Gets/Sets the Label for this segment control"),
         Category("Behavior"),
         DefaultValue("Segment Label"),
         Browsable(true)]
        public String SegmentLabel 
        {
            get 
            {
                return lblSegName.Text;
            } //end get
            set
            {
                lblSegName.Text = value;
            } //end set
        } //end SegmentLabel

        /// <summary>
        /// Changes this Segment Control to handle one of the available segment types
        /// </summary>
        [Description("Changes this segment control to handle one of the available segment types"),
         Category("Behavior"),
         DefaultValue(SegmentTypeEnum.RGBA_Integers),
         Browsable(true)]
        public SegmentTypeEnum SegmentType
        {
            get 
            {
                return m_SegType;
            } //end get
            set 
            {
                switch(value)
                {
                    case SegmentTypeEnum.XY_Floats:
                    case SegmentTypeEnum.XY_Integers:
                        this.pnlSegmentLayout.ColumnStyles[2].Width = 25;
                        this.pnlSegmentLayout.ColumnStyles[3].Width = 25;
                        this.pnlSegmentLayout.ColumnStyles[4].Width = 0;
                        this.pnlSegmentLayout.ColumnStyles[5].Width = 0;
                        this.pnlSegmentLayout.ColumnStyles[6].Width = 0;
                        this.pnlSegmentLayout.ColumnStyles[7].Width = 0;
                        this.lblSegValueA.Text = "X";
                        this.lblSegValueB.Text = "Y";
                        break;
                    case SegmentTypeEnum.RGB_Floats:
                    case SegmentTypeEnum.RGB_Integers:
                        this.pnlSegmentLayout.ColumnStyles[2].Width = 12.5F;
                        this.pnlSegmentLayout.ColumnStyles[3].Width = 12.5F;
                        this.pnlSegmentLayout.ColumnStyles[4].Width = 12.5F;
                        this.pnlSegmentLayout.ColumnStyles[5].Width = 0;
                        this.pnlSegmentLayout.ColumnStyles[6].Width = 30;
                        this.pnlSegmentLayout.ColumnStyles[7].Width = 12.5F;
                        this.lblSegValueA.Text = "R";
                        this.lblSegValueB.Text = "G";
                        this.lblSegValueC.Text = "B";
                        break;
                    case SegmentTypeEnum.RGBA_Floats:
                    case SegmentTypeEnum.RGBA_Integers:
                        this.pnlSegmentLayout.ColumnStyles[2].Width = 10;
                        this.pnlSegmentLayout.ColumnStyles[3].Width = 10;
                        this.pnlSegmentLayout.ColumnStyles[4].Width = 10;
                        this.pnlSegmentLayout.ColumnStyles[5].Width = 10;
                        this.pnlSegmentLayout.ColumnStyles[6].Width = 30;
                        this.pnlSegmentLayout.ColumnStyles[7].Width = 10;
                        this.lblSegValueA.Text = "R";
                        this.lblSegValueB.Text = "G";
                        this.lblSegValueC.Text = "B";
                        this.lblSegValueD.Text = "A";
                        break;
                    case SegmentTypeEnum.Booleans:
                    case SegmentTypeEnum.Floats:
                    case SegmentTypeEnum.Integers:
                    case SegmentTypeEnum.Strings:
                    default:
                        this.pnlSegmentLayout.ColumnStyles[2].Width = 50;
                        this.pnlSegmentLayout.ColumnStyles[3].Width = 0;
                        this.pnlSegmentLayout.ColumnStyles[4].Width = 0;
                        this.pnlSegmentLayout.ColumnStyles[5].Width = 0;
                        this.pnlSegmentLayout.ColumnStyles[6].Width = 0;
                        this.pnlSegmentLayout.ColumnStyles[7].Width = 0;
                        this.lblSegValueA.Text = "Value";
                        break;
                } //end switch

                m_SegType = value;
            } //end set
        } //end SegmentType
        
        /// <summary>
        /// Hides or un-hides the Integer Key Value Column
        /// </summary>
        [Description("Hides or un-hides the Integer Key Value Column"),
         Category("Appearance"),
         DefaultValue(false),
         Browsable(true)]
        public Boolean HideKeys
        {
            get
            {
                return m_HideKeys;
            } //end get
            set
            {
                if (value == true)
                {
                    this.pnlSegmentLayout.ColumnStyles[0].Width = 0;
                } //end if
                else
                {
                    this.pnlSegmentLayout.ColumnStyles[0].Width = 80;
                } //end else
                m_HideKeys = value;
            } //end set
        } //end HideKeys

        /// <summary>
        /// Allow user to edit/modify the key name fields
        /// </summary>
        [Description("Allow user to edit/modify the key name fields"),
         Category("Behavior"),
         DefaultValue(false),
         Browsable(true)]
        public Boolean UnlockKeyNames
        {
            get
            {
                return m_UnlockKeyNames;
            } //end get
            set
            {
                if (value == true)
                {
                    foreach (KeyValuePair<UInt32,RowControls> item in m_Rows)
                    {
                        item.Value.txtKeyName.ReadOnly = false;
                    } //end foreach
                } //end if
                else
                {
                    foreach (KeyValuePair<UInt32, RowControls> item in m_Rows)
                    {
                        item.Value.txtKeyName.ReadOnly = true;
                    } //end foreach
                }
                m_UnlockKeyNames = value;
            } //end set
        } //end UnlockKeyNames

        /// <summary>
        /// Number of Rows in this panel
        /// </summary>
        [Browsable(false)]
        public int RowCount
        {
            get
            {
                return m_Rows.Count;
            } //end get
        } //end RowCount

        #endregion Public Properties

        #region Public Methods

        /// <summary>
        /// Adds a row of controls to the Segment Panel given the key value for the row
        /// </summary>
        /// <param name="intKey">The Key value for the item</param>
        public RowControls AddRow(UInt32 intKey)
        {
            //Do not create the row if it already exists (no duplicate keys allowed)
            if (m_Rows.ContainsKey(intKey))
                {
                return GetRow(intKey);
                } //end if

            //Create the new Row in the SegmentLayout Panel
            int intRowIndex = pnlSegmentLayout.RowCount - 1;
            pnlSegmentLayout.RowCount += 1;
            pnlSegmentLayout.RowStyles.Insert(intRowIndex, new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25));
            
            //Create the new Row Controls and store it in the row dictionary
            RowControls row = new RowControls();
            row.RowIndex = intRowIndex;
            row.Key = intKey;
            m_Rows.Add(intKey, row);
            
            //Add the Row Controls to the new panel row            
            pnlSegmentLayout.Controls.Add(row.txtKey, 0, intRowIndex);
            pnlSegmentLayout.Controls.Add(row.txtKeyName, 1, intRowIndex);
            pnlSegmentLayout.Controls.Add(row.txtValueA, 2, intRowIndex);
            pnlSegmentLayout.Controls.Add(row.txtValueB, 3, intRowIndex);
            pnlSegmentLayout.Controls.Add(row.txtValueC, 4, intRowIndex);
            pnlSegmentLayout.Controls.Add(row.txtValueD, 5, intRowIndex);
            pnlSegmentLayout.Controls.Add(row.btnColor, 6, intRowIndex);
            pnlSegmentLayout.Controls.Add(row.picPreview, 7, intRowIndex);

            //Make any setting modifications as required...
            row.txtKeyName.ReadOnly = (!this.UnlockKeyNames);

            //Show the Row Controls
            row.txtKey.Show();
            row.txtKeyName.Show();
            row.txtValueA.Show();
            row.txtValueB.Show();
            row.txtValueC.Show();
            row.txtValueD.Show();
            row.btnColor.Show();
            row.picPreview.Show();

            return row;
        } //end AddRow

        /// <summary>
        /// Removes a row from the segment panel given the key for an item
        /// </summary>
        /// <param name="intKey">The key value for the item</param>
        public void RemoveRow(UInt32 intKey)
        {
            RowControls row = null;

            //Try retrieving the row from the row dictionary
            if (m_Rows.TryGetValue(intKey, out row))
            {
                //Retrieve the Row index being removed...
                int intRemoveRowIndex = row.RowIndex;

                //Move all controls below this row, up one row.
                foreach (Control ctl in pnlSegmentLayout.Controls)
                {
                    int intRow = pnlSegmentLayout.GetRow(ctl);

                    if (intRow > intRemoveRowIndex)
                    {
                        pnlSegmentLayout.SetRow(ctl, intRow - 1);
                    } //end if
                } //end foreach
                
                //Remove the row from the panel
                pnlSegmentLayout.RowStyles.RemoveAt(intRemoveRowIndex);
                pnlSegmentLayout.RowCount -= 1;

                //Remove the row from the row dictionary
                m_Rows.Remove(intKey);

                //Destroy the row controls
                row.Dispose();
            } //end if
            
        } //end RemoveRow

        /// <summary>
        /// Retrieves the Row controls for a given key value
        /// </summary>
        /// <param name="intKey">the key for a given item</param>
        /// <returns></returns>
        public RowControls GetRow(UInt32 intKey)
        {
            RowControls row = null;

            m_Rows.TryGetValue(intKey, out row);

            return row;

        } //end GetRow

        /// <summary>
        /// Clears all of the rows in the Segment Panel
        /// </summary>
        public void ClearRows() 
        {
            //Loop through every row in the row dictionary
            foreach (RowControls row in m_Rows.Values)
            {
                //Retrieve the Row to be removed...
                int intRemoveRowIndex = row.RowIndex;

                //Destroy the controls in the row
                row.Dispose();

                //Remove the row from the panel
                pnlSegmentLayout.RowStyles.RemoveAt(intRemoveRowIndex);
                pnlSegmentLayout.RowCount -= 1;

            } //end foreach

            //Empty the entire dictionary of rows
            m_Rows.Clear();

        } //end ClearRows

        #endregion Public Methods

    } //end ctlSegmentPanel

} //end LoLEdit
